package com.ops.uitl.common;

import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import com.ops.uitl.config.IConfig;
import com.ops.uitl.config.PropertiesConfig;
import com.ops.uitl.config.XMLConfig;
import com.ops.uitl.data.IData;
import com.ops.uitl.data.IDataset;

public class Common implements Serializable {
	transient protected Logger log = Logger.getLogger(this.getClass());
	public static final int MESSAGE_CONFIRM = 1;
	public static final int MESSAGE_WARNING = 2;
	public static final int MESSAGE_ERROR = 3;

	private static Common common;

	/**
	 * get instance
	 * @return Common
	 */
	public static Common getInstance() {
		if (common == null) {
			common = new Common();
		}
		return common;
	}

	/**
	 * get class resource stream
	 * @param file
	 * @return InputStream
	 * @throws Exception
	 */
	public InputStream getClassResourceStream(String file) throws Exception {
		InputStream in = common.getClass().getClassLoader().getResourceAsStream(file);
		if (in == null) log.error("file " + file + " not exist!");
		return in;
	}

	/**
	 * get class resource
	 * @param file
	 * @return URL
	 * @throws Exception
	 */
	public URL getClassResource(String file) throws Exception {
		URL url = common.getClass().getClassLoader().getResource(file);
		if (url == null) log.error("file " + file + " not exist!");
		return url;
	}

	/**
	 * get config
	 * @param prop
	 * @return String
	 * @throws Exception
	 */
	public String getConfig(String prop) throws Exception {
		return getConfig(prop, null);
	}

	/**
	 * get config
	 * @param prop
	 * @param defval
	 * @return String
	 * @throws Exception
	 */
	public String getConfig(String prop, String defval) throws Exception {
		return getProperty("wadeconfig.xml", prop, defval);
	}

	/**
	 * get property
	 * @param prop
	 * @return String
	 * @throws Exception
	 */
	public String getProperty(String prop) throws Exception {
		return getProperty(prop, null);
	}

	/**
	 * get property
	 * @param prop
	 * @param defval
	 * @return String
	 * @throws Exception
	 */
	public String getProperty(String prop, String defval) throws Exception {
		return getProperty("application.xml", prop, defval);
	}

	/**
	 * get property
	 * @param file
	 * @param prop
	 * @param defval
	 * @return String
	 * @throws Exception
	 */
	public String getProperty(String file, String prop, String defval) throws Exception {
		String result = null;
		try {
			IConfig config = new XMLConfig(file);
			result = config.getProperty(prop);
		} catch (Exception e) {
			if (defval == null) {
				log.error("application config " + prop + " reading error!", e);
			} else {
				result = defval;
			}
		} finally {
			if (result == null && defval != null) {
				result = defval;
			}
		}

		return result;
	}

	/**
	 * get elements
	 * @param path
	 * @return
	 * @throws Exception
	 */
	public IDataset getElements(String path) throws Exception {
		return getElements("application.xml", path);
	}

	/**
	 * 获取元素集合
	 * @param file
	 * @param path
	 * @return
	 * @throws Exception
	 */
	public IDataset getElements(String file, String path) throws Exception {
		IDataset result = null;
		try {
			IConfig config = new XMLConfig(file);
			result = config.getElements(path);
		} catch (Exception e) {
			log.error("application config " + path + " reading error!", e);
		}

		return result;
	}

	/**
	 * get properties
	 * @param prop
	 * @return IData
	 * @throws Exception
	 */
	public IData getProperties(String prop) throws Exception {
		return getProperties("application.xml", prop);
	}

	/**
	 * get property
	 * @param file
	 * @param prop
	 * @return IData
	 * @throws Exception
	 */
	public IData getProperties(String file, String prop) throws Exception {

		try {
			IConfig config = new XMLConfig(file);
			IData result = config.getProperties(prop);
			return result;
		} catch (Exception e) {
			log.error(file + " config " + prop + " reading error!", e);
		}

		return null;
	}

	/**
	 * get property by prop
	 * @param prop
	 * @return String
	 * @throws Exception
	 */
	public String getPropertyByProp(String prop) throws Exception {
		return getPropertyByProp(prop, null);
	}

	/**
	 * get property by prop
	 * @param prop
	 * @param defval
	 * @return String
	 * @throws Exception
	 */
	public String getPropertyByProp(String prop, String defval) throws Exception {
		return getPropertyByProp("build.properties", prop, defval);
	}

	/**
	 * get property by prop
	 * @param file
	 * @param prop
	 * @param defval
	 * @return String
	 * @throws Exception
	 */
	public String getPropertyByProp(String file, String prop, String defval) throws Exception {

		String result = null;
		try {
			IConfig config = new PropertiesConfig(file);
			result = config.getProperty(prop);
		} catch (Exception e) {
			if (defval == null) {
				log.error(file + " config " + prop + " reading error!", e);
			} else {
				result = defval;
			}
		} finally {
			if (result == null && defval != null) {
				result = defval;
			}
		}

		return result;
	}

	/**
	 * encode timestamp
	 * @param timeStr
	 * @return Timestamp
	 * @throws Exception
	 */
	public Timestamp encodeTimestamp(String timeStr) throws Exception {
		String format = getTimestampFormat(timeStr);
		return encodeTimestamp(format, timeStr);
	}

	/**
	 * encode timestamp
	 * @param format
	 * @param timeStr
	 * @return Timestamp
	 * @throws Exception
	 * modified by caom on 08.7.28, check timeStr is null
	 */
	public Timestamp encodeTimestamp(String format, String timeStr) throws Exception {
		if (null == timeStr || "".equals(timeStr))return null;
		if (format.length() != timeStr.length()) format = getTimestampFormat(timeStr);
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return new Timestamp(sdf.parse(timeStr).getTime());
	}

	/**
	 * decode timestamp
	 * @param format
	 * @param timeStr
	 * @return String
	 * @throws Exception
	 */
	public String decodeTimestamp(String format, String timeStr) throws Exception {
		Timestamp time = encodeTimestamp(format, timeStr);
		return decodeTimestamp(format, time);
	}

	/**
	 * decode timestamp
	 * @param format
	 * @param time
	 * @return String
	 * @throws Exception
	 */
	public String decodeTimestamp(String format, Timestamp time) throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(time);
	}

	/**
	 * get current time
	 * @return Timestamp
	 * @throws Exception
	 */
	public Timestamp getCurrentTime() throws Exception {
		return new Timestamp(System.currentTimeMillis());
	}

	/**
	 * get sys time
	 * @return String
	 * @throws Exception
	 */
	public String getSysTime() throws Exception {
		return decodeTimestamp("yyyy-MM-dd HH:mm:ss", new Timestamp(System.currentTimeMillis()));
	}

	/**
	 * get sys date
	 * @return String
	 * @throws Exception
	 */
	public String getSysDate() throws Exception {
		return decodeTimestamp("yyyy-MM-dd", new Timestamp(System.currentTimeMillis()));
	}

	/**
	 * get timestamp format
	 * @param value
	 * @return String
	 */
	public String getTimestampFormat(String value) {
		switch (value.length()) {
			case 4:
				return "yyyy";
			case 6:
				return "yyyyMM";
			case 7:
				return "yyyy-MM";
			case 8:
				return "yyyyMMdd";
			case 10:
				return "yyyy-MM-dd";
			case 13:
				return "yyyy-MM-dd HH";
			case 16:
				return "yyyy-MM-dd HH:mm";
			case 19:
				return "yyyy-MM-dd HH:mm:ss";
			case 21:
				return "yyyy-MM-dd HH:mm:ss.S";
		}
		return null;
	}
	/**
	 * get match str
	 * @param str
	 * @param regex
	 * @return String
	 */
	public String getMatchStr(String str, String regex) {
		List result = getMatchArray(str, regex);
		return result.size() == 0 ? null : (String) result.get(0);
	}

	/**
	 * get match array
	 * @param str
	 * @param regex
	 * @return List
	 */
	public List getMatchArray(String str, String regex) {
		List result = new ArrayList();

		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		while (matcher.find()) {
			result.add(matcher.group());
		}

		return result;
	}

	/**
	 * is matches
	 * @param str
	 * @param regex
	 * @return boolean
	 */
	public boolean isMatches(String str, String regex) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		return matcher.matches();
	}

	/**
	 * trim prefix
	 * @param str
	 * @param suffix
	 * @return String
	 */
	public String trimPrefix(String str, String prefix) {
		return str.startsWith(prefix) ? str.substring(prefix.length()) : str;
	}

	/**
	 * trim suffix
	 * @param str
	 * @param suffix
	 * @return String
	 */
	public String trimSuffix(String str, String suffix) {
		return str.endsWith(suffix) ? str.substring(0, str.length() - 1) : str;
	}

	/**
	 * get str by array
	 * @param array
	 * @return String
	 */
	public String getStrByArray(String[] array) {
		return getStrByArray(array, ",");
	}

	/**
	 * get str by array
	 * @param array
	 * @param split
	 * @return String
	 */
	public String getStrByArray(String[] array, String split) {
		StringBuffer str = new StringBuffer();
		for (int i=0; i<array.length; i++) {
			str.append(array[i] + (i != array.length - 1 ? split : ""));
		}
		return str.toString();
	}

	/**
	 * encode charset
	 * @param charSet
	 * @return String
	 * @throws Exception
	 */
	public String encodeCharset(String charSet) throws Exception {
		return new String(charSet.getBytes("GBK"), "ISO8859_1");
	}

	/**
	 * decode charset
	 * @param charSet
	 * @return String
	 * @throws Exception
	 */
	public String decodeCharset(String charSet) throws Exception {
		return new String(charSet.getBytes("ISO8859_1"),"GBK");
	}

	/**
	 * get values
	 * @param value
	 * @return String[]
	 * @throws Exception
	 */
	public String[] getValues(Object value) throws Exception {
		if (value == null) return new String[] {};
		if (value instanceof String[]) {
			return (String[]) value;
		} else {
			return new String[] { (String) value } ;
		}
	}

	/***
	 * 获取应用目录
	 * @param name
	 * @return
	 */
	public String getDomainPath(String name) {
		String path = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
		if (name == null || "".equals(name))
			return path;

		String[] dirs = name.split("/");
		String pathname = "";
		boolean find = true;
		for (int i = 0; i < dirs.length; i++) {
			int index = path.indexOf(dirs[i]);

			if (index != -1 && find) {
				find = true;
				pathname = path.substring(0, index + dirs[i].length() + 1);
			} else {
				find = false;
				if (i == 0) return "";
				File file = new File(pathname + dirs[i]);
				if (file.exists())
					pathname = pathname + dirs[i] + "/";
				else
					return "";
			}
		}
		return pathname;
	}

	public String getClassRoot(String name) {
		return getClass().getClassLoader().getResource(name).getPath();
	}
}
